package com.yanqu.road.server.manger;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.data.analytics.Provider;
import com.yanqu.data.analytics.ProviderFactory;
import com.yanqu.data.analytics.constant.EventDataConstants;
import com.yanqu.data.analytics.consumer.ConsumerQueueOperate;
import com.yanqu.data.analytics.enums.ePublicEventAttr;
import com.yanqu.data.analytics.enums.eUserAttr;
import com.yanqu.data.analytics.helper.DataBuilder;
import com.yanqu.data.analytics.helper.UserMonitorMetrics;
import com.yanqu.data.analytics.impl.EmptyProvider;
import com.yanqu.road.dao.impl.maidian.UserDayOnlineDataDaoImpl;
import com.yanqu.road.entity.config.battle.BattleResult;
import com.yanqu.road.entity.config.beauty.BeautyInfo;
import com.yanqu.road.entity.config.building.BuildingInfo;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.config.passroad.PassRoadPointInfo;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.config.promotion.PromotionInfo;
import com.yanqu.road.entity.config.vehicle.VehicleInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.estatewar.UserEstateWarData;
import com.yanqu.road.entity.maidian.UserDayOnlineData;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.entity.player.*;
import com.yanqu.road.entity.recharge.RechargeOrder;
import com.yanqu.road.entity.recharge.ThirdPartyRechargeOrder;
import com.yanqu.road.entity.servercenter.ChannelInfo;
import com.yanqu.road.entity.servercenter.DAServerInfo;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.task.TaskInfo;
import com.yanqu.road.entity.tradewar.TradeWarWanted;
import com.yanqu.road.entity.union.UnionInfo;
import com.yanqu.road.entity.union.cross.CrossUnionInfo;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.rank.RankListModel;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.passRoad.PassRoadModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.BuildingModule;
import com.yanqu.road.server.gameplayer.module.player.RechargeModule;
import com.yanqu.road.server.gameplayer.module.task.TaskModule;
import com.yanqu.road.server.gameplayer.module.vehicle.VehicleModule;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.maidian.DayFirstLoginTask;
import com.yanqu.road.server.manger.maidian.DefaultEventTraceAction;
import com.yanqu.road.server.manger.maidian.OnLineLog;
import com.yanqu.road.server.manger.maidian.musicroom.MusicRoomLog;
import com.yanqu.road.server.manger.maidian.pet.PetLog;
import com.yanqu.road.server.manger.manor.ManorMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.manger.union.CrossUnionMgr;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.executor.GeneralTask;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class DataAnalyticsMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(DataAnalyticsMgr.class.getName());

    public static Provider provider = new EmptyProvider(logger);

    private static Map<Long, DataBuilder> commonUserEventDataMap = new ConcurrentHashMap<>();

    private static Map<Long, UserDayOnlineData> userOnlineDataMap = new ConcurrentHashMap<>();

    private static Object lock = new Object();

    //每日登录异步上报快照
    private static ThreadTaskManger threadTaskManger;

    private static AtomicInteger taskId = new AtomicInteger(1);

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        ServerInfo serverInfo = ServerListMgr.getServerInfo(ConfigHelper.getLong("serverId"));
        if(serverInfo == null){
            return false;
        }
        //渠道
        ChannelInfo channelInfo = ServerListMgr.getChannelInfo(serverInfo.getChannelId());
        if(channelInfo == null){
            return false;
        }
        Provider old = provider;
        if(initDataAnalytics()) {
            if(channelInfo.getKafkaCollect() == 1){
                provider = ProviderFactory.getProvider("KAFKA", logger, null);
            }else if(!StringUtils.isNullOrEmpty(channelInfo.getCollectServerUrl())) {
                 provider = ProviderFactory.getProvider("TDA", logger, channelInfo.getCollectServerUrl());
            }
            if(threadTaskManger == null) {
                threadTaskManger = new ThreadTaskManger(2, "DataAnalyticsMgr");
            }
        }else {
            provider = new EmptyProvider(logger);
        }
        logger.info("DataAnalyticsMgr reload");
        old.flush();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        userOnlineDataMap = new UserDayOnlineDataDaoImpl().getUserDayOnlineData();
        return true;
    }

    @Override
    public boolean stop() {
        if(provider != null) {
            provider.flush();
            provider.close();
        }
        return true;
    }

    /**
     * 定时发送
     */
    public static void flush(){
        if(provider != null){
            logger.info("provider {}", provider.getClass().getSimpleName());
            provider.flush();
        }
    }

    @Override
    public boolean save() {
        for (Map.Entry<Long, UserDayOnlineData> entry : userOnlineDataMap.entrySet()) {
            UserDayOnlineData value = entry.getValue();
            if(value.isInsertOption()){
                new UserDayOnlineDataDaoImpl().add(value);
            }else if(value.isUpdateOption()){
                new UserDayOnlineDataDaoImpl().update(value);
            }
        }
        return true;
    }

    /**
     * 修复入口
     */
    public static void repair(String param){
        if(provider != null){
            ConsumerQueueOperate queueOperate = provider.getQueueOperate();
            if(queueOperate != null){
                queueOperate.poll(Integer.valueOf(param));
                logger.debug("poll queue size {}", param);
            }else {
                logger.error("repair fail {}", param);
            }
        }
    }

    /**
     * 是否开启埋点
     */
    public static boolean openDataAnalytics(){
        if(provider.getClass().getSimpleName().equals("EmptyProvider")){
            return false;
        }
        return true;
    }

    /**
     * 是否初始化埋点
     */
    private static boolean initDataAnalytics(){
        ServerInfo serverInfo = ServerListMgr.getServerInfo(ConfigHelper.getLong("serverId"));
        if(serverInfo == null){
            return false;
        }
        ChannelInfo channelInfo = ServerListMgr.getChannelInfo(serverInfo.getChannelId());
        if(channelInfo == null){
            return false;
        }
        if(!channelInfo.isOpenDataAnalytics()){
            return false;
        }
        if(StringUtils.isNullOrEmpty(channelInfo.getCollectServerUrl()) && channelInfo.getKafkaCollect() == 0){
            return false;
        }
        DAServerInfo daServerInfo = DAServerListMgr.get(channelInfo.getChannelId(), serverInfo.getServerId());
        if(daServerInfo == null){
            return false;
        }
        return true;
    }

    /**
     * 获取访客ID
     */
    public static String getDistinctId(UserInfo userInfo){
        return "";
    }

    /**
     * 基本信息类
     */
    private static void buildUserCommonAttr(DataBuilder builder, UserInfo userInfo) {
        int channelId = ServerListMgr.getChannelId(ConfigHelper.getLong("serverId"));
        eChannelType channelType = eChannelType.forValue(channelId);
        if(channelType != null){
            //builder.build(ePublicEventAttr.CHANNEL.getAttrId(), channelId);
        }
        //渠道
        builder.build(ePublicEventAttr.CHANNEL_ID.getAttrId(), channelId);
        //账户;v4.1删除
        //builder.build(ePublicEventAttr.ACCOUNT_ID.getAttrId(), userInfo.getUserId());
        //区服
        builder.build(ePublicEventAttr.SERVER_ID.getAttrId(), GameServer.getInstance().getServerId());
        //角色等级
        builder.build(ePublicEventAttr.CURRENT_LEVEL.getAttrId(), userInfo.getTitleId());
        //open_id
        builder.build(ePublicEventAttr.OPEN_ID.getAttrId(), userInfo.getOpenId());
        //平台id
        builder.build(ePublicEventAttr.PLATFORM_ID.getAttrId(), userInfo.getPlatformUserId());
        //角色名称
        builder.build(ePublicEventAttr.ROLE_NAME.getAttrId(), userInfo.getNickName());
        //区服名称
        ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
        if (serverInfo != null) {
            builder.build(ePublicEventAttr.SERVER_NAME.getAttrId(), serverInfo.getServerName());
        }
        //编号
        //builder.build(ePublicEventAttr.NO.getAttrId(), userInfo.getUserAliasId());

        //vip等级
        builder.build(ePublicEventAttr.VIP_LEVEL.getAttrId(), VipMgr.getVipLv(userInfo.getVipExp()));
        //vip经验
        builder.build(ePublicEventAttr.VIP_EXP.getAttrId(), userInfo.getVipExp());

        //创角/注册时间
        String dateTimeStr = DateHelper.getCurrentDateTimeString(userInfo.getRegisterTime() * 1000);
        if(userInfo.getCreateRoleTime() > 0) {
            builder.build(ePublicEventAttr.CREATE_ROLE_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(userInfo.getCreateRoleTime() * 1000));
        }else {
            builder.build(ePublicEventAttr.CREATE_ROLE_TIME.getAttrId(), dateTimeStr);
        }

        //当前赚速
        builder.build(ePublicEventAttr.CURRENT_SPEED.getAttrId(), userInfo.getEarnSpeed().toString());

        //当前钱庄等级
        builder.build(ePublicEventAttr.CURRENT_HOUSELV.getAttrId(), userInfo.getHouseLv());

        //最后登录时间
        builder.build(ePublicEventAttr.LAST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(userInfo.getLastLoginTime() * 1000));

    }

    /**
     * 填充公共事件属性（最基本的信息）；适用玩家可能不在线
     */
    public static void buildPublicEventData(UserInfo userInfo, DataBuilder builder){

        buildUserCommonAttr(builder, userInfo);

        //声望
        builder.build(ePublicEventAttr.CURRENT_REPUTATION.getAttrId(), userInfo.getPrestige());

        builderCurrentGuild(userInfo, builder);

        //时区
        builder.build(EventDataConstants.ZONE_OFFSET, LocalDateTimeHelper.getDefaultTimeZone());

        builder.build(ePublicEventAttr.USERID_ID.getAttrId(), userInfo.getUserId());

        builder.build(ePublicEventAttr.USERALIAS_ID.getAttrId(), userInfo.getUserAliasId());
    }

    /**
     * 填充公共事件属性（最基本的信息）
     */
    public static void buildPublicEventData(GamePlayer player, DataBuilder builder){

        UserInfo userInfo = player.getUserInfo();

        /**
         * 基本信息类
         */
        buildUserCommonAttr(builder, userInfo);

        //设备id
        builder.build(ePublicEventAttr.DEVICE_ID2.getAttrId(), player.getDeviceId());

        //系统预制
        builder.build(ePublicEventAttr.DEVICE_ID.getAttrId(), player.getDeviceId());
        builder.build(ePublicEventAttr.IP.getAttrId(), player.getIp());
        builder.build(ePublicEventAttr.SYSTEM_LANGUAGE.getAttrId(), player.getLanguage());
        builder.build(ePublicEventAttr.OS.getAttrId(), player.getPhonePlatform() == 1 ? "android" : "ios");

        //时区
        builder.build(EventDataConstants.ZONE_OFFSET, LocalDateTimeHelper.getDefaultTimeZone());

        builder.build(ePublicEventAttr.USERID_ID.getAttrId(), userInfo.getUserId());

        builder.build(ePublicEventAttr.USERALIAS_ID.getAttrId(), userInfo.getUserAliasId());

        //pid
        builder.build(ePublicEventAttr.PID.getAttrId(), player.getAppId());

        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        //声望
        builder.build(ePublicEventAttr.CURRENT_REPUTATION.getAttrId(), userInfo.getPrestige());
        //当前门客赚钱
        builder.build(ePublicEventAttr.CURRENT_GUEST_POWER.getAttrId(), player.getModule(PatronsModule.class).getTotalPatronsAbility().toString());
        //当前关卡
        builder.build(ePublicEventAttr.CURRENT_GAMELEVEL.getAttrId(), getGuanQia(player));
        //当前主线任务
        builder.build(ePublicEventAttr.CURRENT_MAINLINE.getAttrId(), player.getModule(TaskModule.class).getRealMainTaskId());

        //当前商会
        builderCurrentGuild(player.getUserInfo(), builder);

        //当前商铺个数
        builder.build(ePublicEventAttr.CURRENT_STORE_NUMBER.getAttrId(), player.getModule(BuildingModule.class).getBuildingMap().size());

        //门客
        List<Integer> patronsList = getPatronsList(player);
        builder.build(ePublicEventAttr.CURRENT_TALENTS_LIST.getAttrId(), patronsList);


        //知己列表
        buildBeautyList(player, builder, ePublicEventAttr.CURRENT_BEAUTY_LIST.getAttrId());

        //最后充值时间
        long time = attributeModule.getAttribute(ePlayerAttrType.LastRechargeTime);
        if(time > 0){
            builder.build(ePublicEventAttr.LAST_PAY_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(time * 1000));
        }

        //当前见识/阅历
        builder.build(ePublicEventAttr.CURRENT_SENSE.getAttrId(), userInfo.getPatronsExp().longValue());

        /**
         * 积累类
         */
        //累计充值天数
        builder.build(ePublicEventAttr.TOTAL_RECHARGE_DAYS.getAttrId(), countTotalRechargeDays(player));
        //累计付费金额
        builder.build(ePublicEventAttr.T0TAL_RECHARGE_AMOUNT.getAttrId(), countTotalRecharge(player));
        //累计登录天数
        builder.build(ePublicEventAttr.TOTAL_LOGIN_DAYS.getAttrId(), attributeModule.getAttribute(ePlayerAttrType.LoginTotalDays));

        buildBuildExtInfo(player, builder);

        /**
         * 资源类
         */
        //当前元宝
        builder.build(ePublicEventAttr.CURRENT_GOLD.getAttrId(), attributeModule.getAttribute(ePlayerAttrType.Ingots));
        //当前银两
        builder.build(ePublicEventAttr.CURRENT_SLIVER.getAttrId(), userInfo.getSilver());
    }

    private static List<Integer> getPatronsList(GamePlayer player) {
        //门客列表
        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        List<Integer> patronsList = new ArrayList<>();
        for (UserPatrons patrons : patronsModule.getUserPatronsList()) {
            patronsList.add(patrons.getPatronsId());
        }
        return patronsList;
    }

    /**
     * 获取关卡
     */
    private static String getGuanQia(GamePlayer player) {
        UserPassRoad userPassRoad = player.getModule(PassRoadModule.class).getUserPassRoad();
        if (userPassRoad != null) {
            if(userPassRoad.getSessionId() > 0){
                return userPassRoad.getPassId() + "-" + (userPassRoad.getSessionId() - 1);
            }
            PassRoadPointInfo passRoadPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
            if(passRoadPointInfo != null) {
                //重置，这个从0开始
                userPassRoad.setSessionId(passRoadPointInfo.getSessionId() + 1);
                return userPassRoad.getPassId() + "-" + passRoadPointInfo.getSessionId();
            }
        }
        return "";
    }

    /**
     * 当前商会
     */
    private static void builderCurrentGuild(UserInfo userInfo, DataBuilder builder) {
        if(!StringUtils.isNullOrEmpty(userInfo.getUnionUid())){
            UnionInfo unionInfo = CrossUnionMgr.getUnionInfo(userInfo.getUnionUid());
            if(unionInfo != null){
                List<String> unionParams = new ArrayList<>();
                unionParams.add(unionInfo.getUnionName());
                unionParams.add(unionInfo.getUnionUid());
                unionParams.add(UnionConfigMgr.getUnionLv(unionInfo.getExperience()) + "");
                unionParams.add(unionInfo.getMemberCount() + "");
                //排名
                int myRank = RankMgr.getUnionRankList().unlockGetMyRank(unionInfo.getUnionUid());
                unionParams.add(String.valueOf(myRank));
                builder.build(ePublicEventAttr.CURRENT_GUILD.getAttrId(), unionParams);
            }
        }
    }

    /**
     * 创角
     */
    public static void createRole(String platformUserId, String userId, String nickName, String ip) {
        try {
            if (!openDataAnalytics()) return;

            //上报玩家基础信息
            UserInfo userInfo = UserMgr.getUserInfo(Long.valueOf(userId));
            if (userInfo != null) {
                DataBuilder onceDataBuilder = DataBuilder.newBuilder(userId, getDistinctId(userInfo));

                buildOnceUserAttr(userInfo, onceDataBuilder);
                //创角时间
                onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), DateHelper.getCurrentDateTimeString());
                provider.user_setOnce(onceDataBuilder.getAccountId(), onceDataBuilder.getDistinctId(), onceDataBuilder.getDataMap());

                //角色名
                DataBuilder dataBuilder = DataBuilder.newBuilder(userId, getDistinctId(userInfo));
                dataBuilder.build(eUserAttr.ROLE_NAME.getAttrId(), nickName);
                dataBuilder.build(eUserAttr.USERALIAS_ID.getAttrId(), userInfo.getUserAliasId());
                provider.user_set(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), dataBuilder.getDataMap());

                // 事件
                DataBuilder eventDataBuilder = DataBuilder.newBuilder(userId, getDistinctId(userInfo));
                // 公共属性
                buildPublicEventData(userInfo, eventDataBuilder);
                provider.track(eventDataBuilder.getAccountId(), eventDataBuilder.getDistinctId(), "create", eventDataBuilder.getDataMap());
            } else {
                logger.error("createRole user  {} fail", userId);
            }
        }catch (Exception e){
            logger.error("analytics createRole error ", e);
        }
    }

    //构建用户首次属性
    private static void buildOnceUserAttr(UserInfo userInfo, DataBuilder onceDataBuilder) {
        //区服ID
        long serverId = ConfigHelper.getLong("serverId");
        onceDataBuilder.build(eUserAttr.SERVER_ID.getAttrId(), serverId);
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if (serverInfo != null) {
            //区服名称
            onceDataBuilder.build(eUserAttr.SERVER_NAME.getAttrId(), serverInfo.getServerName());
        }
        onceDataBuilder.build(eUserAttr.ROLE_NAME.getAttrId(), userInfo.getNickName());
        //openId
        onceDataBuilder.build(eUserAttr.OPEN_ID.getAttrId(), userInfo.getOpenId());
        //平台Id
        onceDataBuilder.build(eUserAttr.PLATFORM_ID.getAttrId(), userInfo.getPlatformUserId());
        //编号
        //onceDataBuilder.build(eUserAttr.NO.getAttrId(), userInfo.getUserAliasId());
        onceDataBuilder.build(eUserAttr.USERID_ID.getAttrId(), userInfo.getUserId());
        onceDataBuilder.build(eUserAttr.USERALIAS_ID.getAttrId(), userInfo.getUserAliasId());
        //渠道
        int channelId = ServerListMgr.getChannelId(serverId);
        onceDataBuilder.build(eUserAttr.CHANNEL_ID.getAttrId(), channelId);
        //职业/头像
        List<Integer> decorationIdList = StringUtils.stringToIntegerList(userInfo.getDecoration(), DecorationMgr.SPLIT_SEPARATOR);
        if(eChannelType.isMainLandChannel(channelId)){
            //大陆职业
            if(decorationIdList.size() > eDecorationType.Costume.getValue()) {
                onceDataBuilder.build(eUserAttr.INITIAL_VOCATION.getAttrId(), decorationIdList.get(eDecorationType.Costume.getValue()));
            }
        }else {
            //其他头像
            if(decorationIdList.size() > 0) {
                onceDataBuilder.build(eUserAttr.INITIAL_VOCATION.getAttrId(), decorationIdList.get(0));
            }
        }
    }

    /**
     * 登录
     */
    public static void trackUserLogin(GamePlayer player, long lastLoginTime){
        try {

            if (!openDataAnalytics()) return;

            DataBuilder onceDataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            //旧数据，重新设置一次user_setOnce
            buildOnceUserAttr(player.getUserInfo(), onceDataBuilder);

            //创角/注册时间
            String dateTimeStr = DateHelper.getCurrentDateTimeString(player.getUserInfo().getRegisterTime() * 1000);
            //创建账号
            onceDataBuilder.build(eUserAttr.CREATE_ACCOUNT_TIME.getAttrId(), dateTimeStr);
            if(player.getUserInfo().getCreateRoleTime() > 0) {
                onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getCreateRoleTime() * 1000));
            }else {
                onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), dateTimeStr);
            }

            long serverId = ConfigHelper.getInt("serverId");
            ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
            if(serverInfo != null) {
                onceDataBuilder.build(eUserAttr.SERVER_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(serverInfo.getOpenTime() * 1000));

                eChannelType channelType = eChannelType.forValue(serverInfo.getChannelId());
                if(channelType != null){
                    onceDataBuilder.build(eUserAttr.CHANNEL.getAttrId(), channelType.getName());
                }
            }

            if(lastLoginTime > 0) {
                onceDataBuilder.build(eUserAttr.FIRST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(lastLoginTime * 1000));
            }else {
                onceDataBuilder.build(eUserAttr.FIRST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getLastLoginTime() * 1000));
            }

            //设备id
            onceDataBuilder.build(eUserAttr.DEVICE_ID.getAttrId(), player.getDeviceId());
            //pid
            onceDataBuilder.build(eUserAttr.PID.getAttrId(), player.getAppId());
            provider.user_setOnce(onceDataBuilder.getAccountId(), onceDataBuilder.getDistinctId(), onceDataBuilder.getDataMap());

            traceFirstLoginThings(player, lastLoginTime);

            //每次首次登录上报事件
            long zeroTime = DateHelper.getTodayZeroTimeStamp();
            long lastLoginZeroTime = DateHelper.getZeroTimeStamp(lastLoginTime * 1000);
            //是否今日首次登录
            if(zeroTime != lastLoginZeroTime) {
                traceDayLogin(player, lastLoginTime);
            }

            addDayLoginTimes(player);

        }catch (Exception e){
            logger.error("analytics trackUserLogin error ", e);
        }
    }

    /**
     *  处理首次登录事件
     * @param lastLoginTime  上次登录事件
     */
    public static void traceFirstLoginThings(GamePlayer player, long lastLoginTime) {

        try{
            long zeroTime = DateHelper.getTodayZeroTimeStamp();
            long lastLoginZeroTime = DateHelper.getZeroTimeStamp(lastLoginTime * 1000);

            //是否今日首次登录
            if(zeroTime != lastLoginZeroTime) {
                //每日首次登录
                threadTaskManger.addTask(1, new DayFirstLoginTask(player));
            }
        }catch (Exception e){
            logger.error("", e);
        }
    }

    public static void traceDayLogin(GamePlayer player, long lastLoginTime) {

        AttributeModule attributeModule = player.getModule(AttributeModule.class);

        //累计登录天数(每天首次登录)
        DataBuilder loginBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
        loginBuilder.build(eUserAttr.TOTAL_LOGIN_DAYS.getAttrId(), attributeModule.getAttribute(ePlayerAttrType.LoginTotalDays));
        provider.user_set(loginBuilder.getAccountId(), loginBuilder.getDistinctId(), loginBuilder.getDataMap());

        // 登录事件
        DefaultEventTraceAction action = new DefaultEventTraceAction(EventDataConstants.Base.LOGIN, player);
        action.build(EventDataConstants.Base.IS_FIRST_LOGIN, lastLoginTime == 0);
        action.trace();
    }

    /**
     * 登出
     */
    public static void userLogout(GamePlayer player){
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            //商会
            String unionUid = player.getUserInfo().getUnionUid();
            dataBuilder.build(eUserAttr.GUILD_ID.getAttrId(), unionUid);
            if(!StringUtils.isNullOrEmpty(unionUid)){
                CrossUnionInfo unionInfo = CrossUnionMgr.getUnionInfo(unionUid);
                if(unionInfo != null){
                    dataBuilder.build("guild_name", unionInfo.getUnionName());
                }
            }
            //赚速与门客赚钱
            dataBuilder.build(eUserAttr.CURRENT_SPEED.getAttrId(), player.getUserInfo().getEarnSpeed().longValue());
            dataBuilder.build(eUserAttr.CURRENT_GUEST_POWER.getAttrId(), player.getModule(PatronsModule.class).getTotalPatronsAbility().longValue());

            //最后登录时间
            dataBuilder.build(eUserAttr.LAST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getLastLoginTime() * 1000));
            //当前等级
            dataBuilder.build(eUserAttr.CURRENT_LEVEL.getAttrId(), player.getTitleId());
            AttributeModule attributeModule = player.getModule(AttributeModule.class);
            //声望
            dataBuilder.build(eUserAttr.CURRENT_REPUTATION.getAttrId(), player.getUserInfo().getPrestige());
            //关卡
            dataBuilder.build(eUserAttr.CURRENT_GAMELEVEL.getAttrId(), getGuanQia(player));
            //主线任务
            dataBuilder.build(eUserAttr.CURRENT_MAINLINE.getAttrId(), player.getModule(TaskModule.class).getRealMainTaskId());

            //美女列表
            buildBeautyList(player, dataBuilder, eUserAttr.CURRENT_INTIMATE_LIST.getAttrId());

            //门客列表
            List<Integer> patronsList = getPatronsList(player);
            dataBuilder.build(eUserAttr.CURRENT_GUEST_LIST.getAttrId(), patronsList.size());

            dataBuilder.build(eUserAttr.CURRENT_GOLD.getAttrId(), attributeModule.getAttribute(ePlayerAttrType.Ingots));
            //银两
            dataBuilder.build(eUserAttr.CURRENT_SLIVER.getAttrId(), player.getUserInfo().getSilver());

            //见识/阅历
            dataBuilder.build(eUserAttr.CURRENT_SENSE.getAttrId(), player.getUserInfo().getPatronsExp().longValue());

            //当前商铺个数
            dataBuilder.build(eUserAttr.CURRENT_STORE_NUMBER.getAttrId(), player.getModule(BuildingModule.class).getBuildingMap().size());

            //vip 经验与等级
            dataBuilder.build(eUserAttr.VIP_EXP.getAttrId(), player.getUserInfo().getVipExp());
            dataBuilder.build(eUserAttr.VIP_LEVEL.getAttrId(), VipMgr.getVipLv(player.getUserInfo().getVipExp()));
            ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
            dataBuilder.build(eUserAttr.CURRENT_SERVERTYPE.getAttrId(), serverInfo.getSpecialServer());

            buildBuildExtInfo(player, dataBuilder);

            provider.user_set(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), dataBuilder.getDataMap());

            MusicRoomLog.trackLogoutMusicInfo(player);

            addDayOnlineTime(player, DateHelper.getCurrentSecond() - player.getUserInfo().getLastLoginTime());

        }catch (Exception e){
            logger.error("analytics trackUserLogout error ", e);
        }
    }

    /**
     * 商铺的加成
     */
    public static void buildBuildExtInfo(GamePlayer player, DataBuilder dataBuilder) {
        //商店赚钱固定值
        List<Map<String, Object>> objectGroup = new ArrayList<>();
        BuildingModule buildingModule = player.getModule(BuildingModule.class);
        for (Map.Entry<Integer, UserBuilding> entry : buildingModule.getBuildingMap().entrySet()) {
            Map<String, Object> objectMap = new HashMap<>();
            UserBuilding building = entry.getValue();
            BuildingInfo buildingInfo = BuildingMgr.getBuildingInfo(building.getBuildingId());
            if(buildingInfo == null){
                continue;
            }
            BigDecimal h = buildingInfo.getStaffEarnSpeed();
            //庄园对伙计赚速加成
            h = h.add(BuildingMgr.getManorStaffEarnAddValue(player, building).divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_UP));
            //药铺对伙计赚钱加成
            h = h.add(BuildingMgr.getDrugStoreEarnAddValue(player, building).divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_UP));
            objectMap.put("current_shop_id", entry.getKey());
            objectMap.put("current_shop_guy", h.doubleValue());
            objectMap.put("current_shop_guynum", building.getStaffCount());
            objectGroup.add(objectMap);
        }
        dataBuilder.build("current_shop_speedbase", objectGroup);

        //商铺赚速加成
        objectGroup = new ArrayList<>();
        for (Map.Entry<Integer, UserBuilding> entry : buildingModule.getBuildingMap().entrySet()) {
            Map<String, Object> objectMap = new HashMap<>();
            UserBuilding building = entry.getValue();
            BuildingInfo buildingInfo = BuildingMgr.getBuildingInfo(building.getBuildingId());
            if (buildingInfo == null) {
                continue;
            }
            objectMap.put("current_shop_id", entry.getKey());
            objectMap.put("current_shop_add", BuildingMgr.getBuildAddition(player, building, buildingInfo).doubleValue());
            objectGroup.add(objectMap);
        }
        dataBuilder.build("current_shop_speedadd", objectGroup);
    }

    private static void buildBeautyList(GamePlayer player, DataBuilder dataBuilder, String attrId) {
        BeautyModule beautyModule = player.getModule(BeautyModule.class);
        //列表改成 数值
        dataBuilder.build(attrId, beautyModule.getBeautyMap().size());
    }

    private static List<String> getPetList(GamePlayer player) {
        List<String> petList = new ArrayList<>();
        VehicleModule vehicleModule = player.getModule(VehicleModule.class);
        for (Map.Entry<String, UserVehicle> vehicleEntry : vehicleModule.getUserVehicleMap().entrySet()) {
            petList.add(vehicleEntry.getKey());
        }
        return petList;
    }

    /**
     * 离线收益
     */
    public static void trackOffline(GamePlayer player, int offlineTime, String silver) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            // 公共属性
            buildPublicEventData(player, dataBuilder);
            // 离线时长
            dataBuilder.build(EventDataConstants.Task.ONLINE_OFFLINE_TIME, offlineTime);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Task.ONLINE, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackOffline error ", e);
        }
    }

    /**
     * 身份升级
     */
    public static void trackTitleUpgrade(GamePlayer player){
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            // 公共属性
            buildPublicEventData(player, dataBuilder);
            // 身份等级
            dataBuilder.build(EventDataConstants.Base.LEVEL_UP_NEW_LEVEL, player.getTitleId());
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Base.LEVEL_UP, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackTitleUpgrade error ", e);
        }
    }

    /**
     * 订单完成
     */
    public static void trackOrderFinish(RechargeOrder rechargeOrder, MallInfo mallInfo){
        try {
            if (!openDataAnalytics()) return;
            if(rechargeOrder.getOrderType() == 1){
                return;
            }
            UserInfo userInfo;
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(rechargeOrder.getUserId());
            if(player != null){
                userInfo = player.getUserInfo();
            }else {
                userInfo = UserMgr.getUserInfo(rechargeOrder.getUserId());
            }
            if (userInfo != null) {
                DataBuilder dataBuilder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
                //防止时间差
                if(rechargeOrder.getUpdateTime() != null) {
                    dataBuilder.build("#time", DateHelper.getCurrentDateTimeString(rechargeOrder.getUpdateTime().getTime()));
                }
                dataBuilder.build(EventDataConstants.Order.ORDER_ID, rechargeOrder.getOrderNo());
                dataBuilder.build(EventDataConstants.Order.ORDER_PLATID, rechargeOrder.getPlatformOrderNo());
                dataBuilder.build(EventDataConstants.Order.ORDER_SDKID, rechargeOrder.getSdkOrderNo());
                if("RMB".equalsIgnoreCase(rechargeOrder.getCurrency())){
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_TYPE, "CNY");
                }else {
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_TYPE, rechargeOrder.getCurrency());
                }
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_AMOUNT, rechargeOrder.getAmount());
                dataBuilder.build(EventDataConstants.Order.PAY_REASON_ID, rechargeOrder.getMallId());
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_REASON, rechargeOrder.getMallName());
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_IS_FIRST_PAY, rechargeOrder.getVipExp() == 0);
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_METHOD, rechargeOrder.getPayType());
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_ENTRANCE, rechargeOrder.getShopType());
                dataBuilder.build(EventDataConstants.Order.PAY_WAY, rechargeOrder.getOrderType());
                dataBuilder.build("pay_reason_markid", rechargeOrder.getMallMarkId());
                dataBuilder.build("pay_channel", rechargeOrder.getPayChannel());
                dataBuilder.build(EventDataConstants.Order.PAY_ISTHIRD, false);
                if(mallInfo != null){
                    dataBuilder.build(EventDataConstants.Order.ORDER_TYPE, mallInfo.getActivityType());
                }
                if(player != null) {
                    buildPublicEventData(player, dataBuilder);
                }else {
                    buildPublicEventData(userInfo, dataBuilder);
                }
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Order.ORDER_FINISH, dataBuilder.getDataMap());

                if(DateHelper.getCurrentSecond() - userInfo.getLastLoginTime() > 7 * DateHelper.DAY_SECONDS){
                    DataBuilder onceDataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
                    //旧数据，重新设置一次user_setOnce
                    buildOnceUserAttr(player.getUserInfo(), onceDataBuilder);

                    //创角/注册时间
                    String dateTimeStr = DateHelper.getCurrentDateTimeString(player.getUserInfo().getRegisterTime() * 1000);
                    //创建账号
                    onceDataBuilder.build(eUserAttr.CREATE_ACCOUNT_TIME.getAttrId(), dateTimeStr);
                    if(player.getUserInfo().getCreateRoleTime() > 0) {
                        onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getCreateRoleTime() * 1000));
                    }else {
                        onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), dateTimeStr);
                    }

                    long serverId = ConfigHelper.getInt("serverId");
                    ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
                    if(serverInfo != null) {
                        onceDataBuilder.build(eUserAttr.SERVER_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(serverInfo.getOpenTime() * 1000));

                        eChannelType channelType = eChannelType.forValue(serverInfo.getChannelId());
                        if(channelType != null){
                            onceDataBuilder.build(eUserAttr.CHANNEL.getAttrId(), channelType.getName());
                        }
                    }

                    onceDataBuilder.build(eUserAttr.FIRST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getLastLoginTime() * 1000));

                    //设备id
                    onceDataBuilder.build(eUserAttr.DEVICE_ID.getAttrId(), player.getDeviceId());
                    //pid
                    onceDataBuilder.build(eUserAttr.PID.getAttrId(), player.getAppId());
                    provider.user_setOnce(onceDataBuilder.getAccountId(), onceDataBuilder.getDistinctId(), onceDataBuilder.getDataMap());
                }
            }

        }catch (Exception e){
            logger.error("analytics trackOrderFinish error ", e);
        }
    }

    /**
     * 订单完成-第三方
     */
    public static void trackOrderFinish(ThirdPartyRechargeOrder thirdPartyRechargeOrder){
        try {

            if (!openDataAnalytics()) return;

            if(thirdPartyRechargeOrder.getOrderType() == 1){
                return;
            }

            UserInfo userInfo;
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(thirdPartyRechargeOrder.getUserId());
            if(player != null){
                userInfo = player.getUserInfo();
            }else {
                userInfo = UserMgr.getUserInfo(thirdPartyRechargeOrder.getUserId());
            }
            if (userInfo != null) {
                DataBuilder dataBuilder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
                //防止时间差
                if(thirdPartyRechargeOrder.getUpdateTime() != null) {
                    dataBuilder.build("#time", DateHelper.getCurrentDateTimeString(thirdPartyRechargeOrder.getUpdateTime().getTime()));
                }
                dataBuilder.build(EventDataConstants.Order.ORDER_ID, "");
                dataBuilder.build(EventDataConstants.Order.ORDER_PLATID, thirdPartyRechargeOrder.getPlatformOrderNo());
                dataBuilder.build(EventDataConstants.Order.ORDER_SDKID, thirdPartyRechargeOrder.getSdkOrderNo());
                if("RMB".equalsIgnoreCase(thirdPartyRechargeOrder.getCurrency())){
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_TYPE, "CNY");
                }else {
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_TYPE, thirdPartyRechargeOrder.getCurrency());
                }
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_AMOUNT, thirdPartyRechargeOrder.getAmount());
                dataBuilder.build(EventDataConstants.Order.PAY_REASON_ID, thirdPartyRechargeOrder.getMallId());
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_IS_FIRST_PAY, thirdPartyRechargeOrder.getVipExp() == 0);
                dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_METHOD, 0);
                dataBuilder.build(EventDataConstants.Order.PAY_WAY, thirdPartyRechargeOrder.getOrderType());
                dataBuilder.build(EventDataConstants.Order.PAY_ISTHIRD, true);
                dataBuilder.build("pay_reason_markid", thirdPartyRechargeOrder.getMallMarkId());
                dataBuilder.build("pay_channel", thirdPartyRechargeOrder.getPayChannel());
                MallInfo mallInfo = MallMgr.getMallInfoByMallId(thirdPartyRechargeOrder.getMallId());
                if(mallInfo != null){
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_REASON, mallInfo.getMallName());
                    dataBuilder.build(EventDataConstants.Order.ORDER_TYPE, mallInfo.getActivityType());
                    dataBuilder.build(EventDataConstants.Order.ORDER_FINISH_PAY_ENTRANCE, mallInfo.getShopType());
                }

                if(player != null){
                    buildPublicEventData(player, dataBuilder);
                }else {
                    buildPublicEventData(userInfo, dataBuilder);
                }
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Order.ORDER_FINISH, dataBuilder.getDataMap());

                if(DateHelper.getCurrentSecond() - userInfo.getLastLoginTime() > 7 * DateHelper.DAY_SECONDS){
                    DataBuilder onceDataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
                    //旧数据，重新设置一次user_setOnce
                    buildOnceUserAttr(player.getUserInfo(), onceDataBuilder);

                    //创角/注册时间
                    String dateTimeStr = DateHelper.getCurrentDateTimeString(player.getUserInfo().getRegisterTime() * 1000);
                    //创建账号
                    onceDataBuilder.build(eUserAttr.CREATE_ACCOUNT_TIME.getAttrId(), dateTimeStr);
                    if(player.getUserInfo().getCreateRoleTime() > 0) {
                        onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getCreateRoleTime() * 1000));
                    }else {
                        onceDataBuilder.build(eUserAttr.CREATE_ROLE_TIME.getAttrId(), dateTimeStr);
                    }

                    long serverId = ConfigHelper.getInt("serverId");
                    ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
                    if(serverInfo != null) {
                        onceDataBuilder.build(eUserAttr.SERVER_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(serverInfo.getOpenTime() * 1000));

                        eChannelType channelType = eChannelType.forValue(serverInfo.getChannelId());
                        if(channelType != null){
                            onceDataBuilder.build(eUserAttr.CHANNEL.getAttrId(), channelType.getName());
                        }
                    }

                    onceDataBuilder.build(eUserAttr.FIRST_LOGIN_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(player.getUserInfo().getLastLoginTime() * 1000));

                    //设备id
                    onceDataBuilder.build(eUserAttr.DEVICE_ID.getAttrId(), player.getDeviceId());
                    //pid
                    onceDataBuilder.build(eUserAttr.PID.getAttrId(), player.getAppId());
                    provider.user_setOnce(onceDataBuilder.getAccountId(), onceDataBuilder.getDistinctId(), onceDataBuilder.getDataMap());
                }
            }
        }catch (Exception e){
            logger.error("analytics thirdPart trackOrderFinish error ", e);
        }
    }

    /**
     * 首次充值时间
     */
    public static void firstPayTime(GamePlayer player, long time){
        try {
            if (!openDataAnalytics()) return;

            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            if(time > 0){
                builder.build(eUserAttr.FIRST_PAY_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(time));
            }else {
                builder.build(eUserAttr.FIRST_PAY_TIME.getAttrId(), DateHelper.getCurrentDateTimeString());
            }
            provider.user_setOnce(builder.getAccountId(), builder.getDistinctId(), builder.getDataMap());
        }catch (Exception e){
            logger.error("analytics firstPayTime error ", e);
        }
    }

    /**
     * 充值埋点
     */
    public static void allRechargeInfo(GamePlayer player){
        try {
            if (!openDataAnalytics()) return;

            //AttributeModule attributeModule = player.getModule(AttributeModule.class);

            UserInfo userInfo = player.getUserInfo();

            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            //累计充值天数
            builder.build(eUserAttr.TOTAL_RECHARGE_DAYS.getAttrId(), countTotalRechargeDays(player));
            //累计付费金额
            builder.build(eUserAttr.TOTAL_RECHARGE_AMOUNT.getAttrId(), countTotalRecharge(player));

            //最后充值时间
            //long lastPayTime = attributeModule.getAttribute(ePlayerAttrType.LastRechargeTime) * 1000;
            builder.build(eUserAttr.LAST_PAY_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(System.currentTimeMillis()));



            //vip 经验与等级
            builder.build(eUserAttr.VIP_EXP.getAttrId(), userInfo.getVipExp());
            builder.build(eUserAttr.VIP_LEVEL.getAttrId(), VipMgr.getVipLv(userInfo.getVipExp()));

            provider.user_set(builder.getAccountId(), builder.getDistinctId(), builder.getDataMap());
        }catch (Exception e){
            logger.error(e);
        }
    }

    /**
     * 从订单获取累计充值天数
     */
    public static int countTotalRechargeDays(GamePlayer player){
        RechargeModule module = player.getModule(RechargeModule.class);
        Map<String, Integer> map1 = module.getRechargeDaysFromOrder();
        Map<String, Integer> map2 = module.getRechargeDaysFromThridPartOrder();
        map1.putAll(map2);
        return map1.size();
    }

    /**
     * 从订单获取累计充值金额
     */
    public static long countTotalRecharge(GamePlayer player){
        RechargeModule module = player.getModule(RechargeModule.class);
        long account = module.getRechargeAccount();
        return account + module.getThirdRechargeAccount();
    }


    /**
     * 任务与奖励
     */
    public static void trackTaskCompleteAndGetReward(GamePlayer player, TaskInfo taskInfo) {

        try {

            if (!openDataAnalytics()) return;

            DataBuilder commonParams = new DataBuilder();
            buildPublicEventData(player, commonParams);

            //完成任务
            if (taskInfo.getType() != eTaskType.Achievement.getValue()) {
                DataBuilder completedBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
                completedBuilder.getDataMap().putAll(commonParams.getDataMap());
                completedBuilder.build(EventDataConstants.Task.COMPLETED_TYPE, taskInfo.getType());
                completedBuilder.build(EventDataConstants.Task.COMPLETED_ID, taskInfo.getTaskId());
                //completedBuilder.build(EventDataConstants.Task.COMPLETED_NAME, taskInfo.getTaskId());
                provider.track(completedBuilder.getAccountId(), completedBuilder.getDistinctId(), EventDataConstants.Task.COMPLETED, completedBuilder.getDataMap());
            }

            //领取成就奖励
            if (taskInfo.getType() == eTaskType.Achievement.getValue()) {
                DataBuilder completedBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
                completedBuilder.getDataMap().putAll(commonParams.getDataMap());
                completedBuilder.build(EventDataConstants.Task.ARCHIEVEMENT_TYPE, taskInfo.getType());
                completedBuilder.build(EventDataConstants.Task.ARCHIEVEMENT_NAME, taskInfo.getTaskId());
                provider.track(completedBuilder.getAccountId(), completedBuilder.getDistinctId(), EventDataConstants.Task.ARCHIEVEMENT, completedBuilder.getDataMap());
            }
        }catch (Exception e){
            logger.error("analytics trackTaskCompleteAndGetReward error ", e);
        }

    }

    /**
     * 任务与奖励(限时任务)
     */
    public static void trackTaskActivity(GamePlayer player, int conditionId, int conditionType) {
        try {

            if (!openDataAnalytics()) return;
            DataBuilder completedBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            completedBuilder.build(EventDataConstants.Task.LIMIT_REWARD_NAME, conditionId);
            completedBuilder.build(EventDataConstants.Task.LIMIT_REWARD_TYPE, conditionType);
            buildPublicEventData(player, completedBuilder);
            provider.track(completedBuilder.getAccountId(), completedBuilder.getDistinctId(), EventDataConstants.Task.LIMIT, completedBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackTaskActivity error ", e);
        }
    }

    /**
     * 珍兽模块 获得珍兽
     */
    public static void trackVehicleGetPet(GamePlayer player,UserVehicle userVehicle) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderVehicleDataBuilder(player,userVehicle);

            VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
            builder.build(EventDataConstants.Vehicle.PET_FIRSTSKILL, vehicleInfo.getDefaultSkillCount());

            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Vehicle.GET_PET, builder.getDataMap());

        }catch (Exception e){
            logger.error("写入TA平台数据异常。珍兽模块 获得珍兽",e);
        }
    }

    /**
     * 珍兽模块 升级珍兽
     */
    public static void trackVehiclePetLevelUp(GamePlayer player, UserVehicle userVehicle) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderVehicleDataBuilder(player,userVehicle);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Vehicle.PET_LEVELUP, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。珍兽模块 升级珍兽",e);
        }
    }

    /**
     * 珍兽模块 放归珍兽
     */
    public static void trackVehicleBackPet(GamePlayer player,UserVehicle userVehicle) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderVehicleDataBuilder(player,userVehicle);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Vehicle.BACK_PET, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。珍兽模块 放归珍兽",e);
        }
    }

    private static DataBuilder builderVehicleDataBuilder(GamePlayer player, UserVehicle userVehicle){
        DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        builder.build(EventDataConstants.Vehicle.PET_ID, userVehicle.getVehicleUid());
        builder.build(EventDataConstants.Vehicle.PET_NAME, userVehicle.getTemplateId());
        // 光环技能
        builder.build(EventDataConstants.Vehicle.PET_HALO, PetLog.getOtherSkillArray(userVehicle));
        builder.build(EventDataConstants.Vehicle.PET_QUALITY, vehicleInfo.getQuality());
        // 计算
        long qualification = VehicleMgr.getVehicleQualification(userVehicle.getTemplateId(), userVehicle.getLevel());
        builder.build(EventDataConstants.Vehicle.PET_INTELLIGENCE, qualification);
        builder.build(EventDataConstants.Vehicle.PET_LEVEL, userVehicle.getLevel());
        buildPublicEventData(player, builder);
        return builder;
    }

    /**
     * 徒弟模块 获得徒弟
     */
    public static void trackChildGetPupil(GamePlayer player, UserChildSite childSite) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderChildInfo(player, childSite);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Child.GET_PUPIL, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。徒弟模块 获得徒弟", e);
        }
    }

    /**
     * 徒弟模块 徒弟成年
     */
    public static void trackPupilAdult(GamePlayer player, UserChildSite childSite, BigInteger childEarnSpeed, boolean isLonely) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderChildInfo(player, childSite);
            builder.build(EventDataConstants.Child.PUPIL_ISLONELY, isLonely);
            builder.build(EventDataConstants.Child.PUPIL_SPEED, childEarnSpeed.longValue());
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Child.PUPIL_ADULT, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。徒弟模块 获得徒弟", e);
        }
    }

    private static DataBuilder builderChildInfo(GamePlayer player, UserChildSite childSite){
        DataBuilder builder = DataBuilder.newBuilder(player.getUserId(), getDistinctId(player.getUserInfo()));
        //builder.build(EventDataConstants.Child.PUPIL_NAME, childSite.getChildName());
        builder.build(EventDataConstants.Child.PUPIL_SEX, childSite.getChildSex());
        builder.build(EventDataConstants.Child.PUPIL_QUALITY, childSite.getChildTalent());
        builder.build(EventDataConstants.Child.PUPIL_VOCATION, childSite.getChildOccupation());
        buildPublicEventData(player, builder);
        return builder;
    }

    private static DataBuilder builderChildInfo(GamePlayer player, MarriageInfo child){
        DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
        builder.build(EventDataConstants.Child.PUPIL_NAME, child.getChildName());
        builder.build(EventDataConstants.Child.PUPIL_SEX, child.getChildSex());
        builder.build(EventDataConstants.Child.PUPIL_QUALITY, child.getChildTalent());
        builder.build(EventDataConstants.Child.PUPIL_VOCATION, child.getChildOccupation());
        buildPublicEventData(player, builder);
        return builder;
    }

    /**
     * 联姻模块 联姻成功
     */
    public static void trackMarriageMarrySuccess(MarriageInfo child1, MarriageInfo child2,boolean isCrossMarriage,
                                                 boolean isUnionMarriage) {
        try{
            if (!openDataAnalytics()) return;
            trackMarriageMarrySuccessChild(child1,child2,isCrossMarriage,isUnionMarriage);
            trackMarriageMarrySuccessChild(child2,child1,isCrossMarriage,isUnionMarriage);
        }catch (Exception e){
            logger.error("写入TA平台数据异常。联姻模块 联姻成功", e);
        }
    }

    private static void trackMarriageMarrySuccessChild(MarriageInfo child1, MarriageInfo child2,boolean isCrossMarriage,
                                                       boolean isUnionMarriage){
        UserInfo userInfo = UserMgr.getUserInfo(child1.getUserId());
        if(userInfo == null){
            return;
        }
        DataBuilder builder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
        builder.build(EventDataConstants.Marriage.PUPIL_NAME, child1.getChildName());
        builder.build(EventDataConstants.Marriage.IS_SAME_GUILDE, isUnionMarriage);
        builder.build(EventDataConstants.Marriage.IS_SAME_SERVER, !isCrossMarriage);
        builder.build(EventDataConstants.Marriage.OTHER_ID, child2.getUserId());
        builder.build(EventDataConstants.Marriage.MY_SPEED, child1.getChildEarnSpeed());
        builder.build(EventDataConstants.Marriage.OTHER_SPEED, child2.getChildEarnSpeed());
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(child1.getUserId());
        if(player != null){
            buildPublicEventData(player, builder);
        }else {
            buildPublicEventData(userInfo, builder);
        }
        provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Marriage.MARRY_SUCCESS, builder.getDataMap());
    }

    /**
     * 联姻模块 孤独终老
     */
    public static void trackMarriageDieAlone(GamePlayer player,MarriageInfo child) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = builderChildInfo(player, child);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Marriage.DIE_ALONE, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。联姻模块 孤独终老", e);
        }
    }

    /**
     * 财神庙模块 祈福
     */
    public static void trackMammonWorshipPray(GamePlayer player) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.MammonWorship.PRAY, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。财神庙模块 祈福", e);
        }
    }

    /**
     * 财神庙模块 膜拜财神
     */
    public static void trackMammonWorshipGod(GamePlayer player,int godType) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.MammonWorship.GOD_TYPE, godType);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.MammonWorship.WORKSHIP_GOD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。财神庙模块 膜拜财神", e);
        }
    }

    /**
     * 财神庙模块 晋升财神
     */
    public static void trackMammonWorshipPromotionGod(UserInfo userInfo,int godType) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
            builder.build(EventDataConstants.MammonWorship.GOD_TYPE, godType);
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(userInfo.getUserId());
            if(player != null){
                buildPublicEventData(player, builder);
            }else {
                buildPublicEventData(userInfo, builder);
            }
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.MammonWorship.PROMOTION_GOD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。财神庙模块 晋升财神", e);
        }
    }

    /**
     * 商会模块 加入商会
     */
    public static void trackUnionJoinGuild(UserInfo userInfo,UnionInfo unionInfo,int position) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = createUnionBuilder(userInfo,unionInfo,position);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.JOIN_GUILD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商会模块 加入商会", e);
        }
    }

    /**
     * 商会模块 离开商会
     */
    public static void trackUnionLeaveGuild(long userId,UnionInfo unionInfo,int position) {
        try{
            if (!openDataAnalytics()) return;
            UserInfo userInfo = UserMgr.getUserInfo(userId);
            DataBuilder builder = createUnionBuilder(userInfo,unionInfo,position);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.LEAVE_GUILD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商会模块 离开商会", e);
        }
    }

    /**
     * 商会模块 商会解散
     */
    public static void trackUnionBreakGuild(GamePlayer player, UnionInfo unionInfo) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = createUnionBuilder(player.getUserInfo(),unionInfo,null);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.BREAK_GUILD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商会模块 离开商会", e);
        }
    }

    /**
     * 商会模块 创建商会
     */
    public static void trackUnionCreateGuild(GamePlayer player, UnionInfo unionInfo) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = createUnionBuilder(player.getUserInfo(),unionInfo,null);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.CREATE_GUILD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商会模块 离开商会", e);
        }
    }

    private static DataBuilder createUnionBuilder(UserInfo userInfo,UnionInfo unionInfo,Integer position){
        DataBuilder builder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
        builder.build(EventDataConstants.Union.GUILD_LEVEL, UnionConfigMgr.getUnionLv(unionInfo.getExperience()));
        builder.build(EventDataConstants.Union.GUILD_ID, unionInfo.getUnionUid());
        builder.build(EventDataConstants.Union.GUILD_NAME, unionInfo.getUnionName());
        if(position != null){
            builder.build(EventDataConstants.Union.GUILD_POSITION, position);
        }
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userInfo.getUserId());
        if(player != null){
            buildPublicEventData(player, builder);
        }else {
            buildPublicEventData(userInfo, builder);
        }
        return builder;
    }

    /**
     * 获取玩家缓存的对象组
     * 并清理数据
     */
    public static List<Map<String, Object>>  popUserMapData(long userId, Map<Long, List<Map<String, Object>>> map){
        List<Map<String, Object>> list;
        synchronized (map){
            list = map.get(userId);
            if(list == null){
                return null;
            }
            map.put(userId, new ArrayList<>());
        }

        return list;
    }

    /**
     * 获取玩家缓存的对象组
     * 超过500则重新存储
     */
    public static List<Map<String, Object>> getUserMapDataForNew(long userId, Map<Long, List<Map<String, Object>>> map) {
        List<Map<String, Object>> list;
        synchronized (map){
            list = map.get(userId);
            if(list == null){
                list = new ArrayList<>();
                map.put(userId, list);
            }
            if(list.size() + 1 >= EventDataConstants.ARRAY_OBJECT_MAX_SIZE){
                map.put(userId, new ArrayList<>());
            }
        }
        return list;
    }

    /**
     * 商战 通缉
     */
    public static void trackOreWarWanted(GamePlayer player, TradeWarWanted warWanted) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.OreWar.WANTED_ID, warWanted.getWantedUid());
            builder.build(EventDataConstants.OreWar.WANTED_USERID, warWanted.getUserId());
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.OreWar.WANTED, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 通缉", e);
        }
    }

    /**
     * 商战 升级税所
     */
    public static void trackOreWarTaxOffice(GamePlayer player,int afterLevel) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.OreWar.AFTER_LEVEL, afterLevel);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.OreWar.TAX_OFFICE, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 通缉", e);
        }
    }

    /**
     * 商战 战斗
     */
    public static void trackOreWarBattle(GamePlayer player, List<BattleResult> battleResultList) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            if(battleResultList.size() > 1){
                builder.build(EventDataConstants.OreWar.BATTLE_TYPE, 1);
            }else {
                builder.build(EventDataConstants.OreWar.BATTLE_TYPE, 0);
            }
            Property property = new Property();
            List<Integer> guestIdList = new ArrayList<>();
            for (BattleResult battleResult : battleResultList) {
                guestIdList.addAll(battleResult.getMyPatronsIdList());
                property.addProperty(PropertyHelper.parseStringToProperty(battleResult.getReward()));
            }
            builder.build(EventDataConstants.OreWar.GUEST_LIST, guestIdList);
            List<Map<String, Object>> objectGroup = new ArrayList<>();
            for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                Map<String, Object> map = new HashMap<>();
                map.put(EventDataConstants.Shop.ITEM_ID, entry.getKey());
                map.put(EventDataConstants.Shop.ITEM_NUM, entry.getValue().longValue());
                objectGroup.add(map);
            }
            builder.build(EventDataConstants.OreWar.BATTLE_RESULT, objectGroup);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.OreWar.BATTLE, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 战斗", e);
        }
    }

    /**
     * 商战 派遣议事厅
     */
    public static void trackOreWarAssemblyhall(GamePlayer player, int patronsId, long earnSpeed) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.Patrons.GUEST_ID, patronsId);
            UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
            int patronsLv = 0;
            if(null != userPatrons){
                patronsLv = userPatrons.getLevel();
            }
            builder.build(EventDataConstants.Patrons.GUEST_LEVEL, patronsLv);
            builder.build(EventDataConstants.Union.ASSEMBLYHALL_SPEED, earnSpeed);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.ASSEMBLYHALL, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 派遣议事厅", e);
        }
    }

    /**
     * 商战 开启商贸路线
     */
    public static void trackOreWarOpenRoad(GamePlayer player,int routeId) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.Union.ROAD_NAME, routeId);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.OPEN_ROAD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 开启商贸路线", e);
        }
    }
    /**
     * 商战 参与商贸
     */
    public static void trackOreWarJoinRoad(GamePlayer player,int routeId) {
        try{
            if (!openDataAnalytics()) return;
            DataBuilder builder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            builder.build(EventDataConstants.Union.ROAD_NAME, routeId);
            buildPublicEventData(player, builder);
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.JOIN_ROAD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 参与商贸", e);
        }
    }
    /**
     * 商战 获得商贸奖励
     */
    public static void trackOreWarGetRoadReward(long userId,int routeId, String reward) {
        try{
            if (!openDataAnalytics()) return;
            UserInfo userInfo = UserMgr.getUserInfo(userId);
            DataBuilder builder = DataBuilder.newBuilder(userId + "", getDistinctId(userInfo));
            builder.build(EventDataConstants.Union.ROAD_NAME, routeId);
            GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
            if(player != null){
                buildPublicEventData(player, builder);
            }else {
                buildPublicEventData(userInfo, builder);
            }
            if(!StringUtils.isNullOrEmpty(reward)){
                List<Map<String, Object>> list = new ArrayList<>();
                Property property = PropertyHelper.parseStringToProperty(reward);
                for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put(EventDataConstants.Shop.ITEM_ID, entry.getKey());
                    map.put(EventDataConstants.Shop.ITEM_NUM, entry.getValue().longValue());
                    list.add(map);
                }
                builder.build(EventDataConstants.Union.ROAD_REWARD, list);
            }
            provider.track(builder.getAccountId(), builder.getDistinctId(), EventDataConstants.Union.GET_ROAD_REWARD, builder.getDataMap());
        }catch (Exception e){
            logger.error("写入TA平台数据异常。商战 获得商贸奖励", e);
        }
    }

    /**
     * 门客结识
     */
    public static void trackAddPatrons(GamePlayer player, PatronsInfo patronsInfo, UserPatrons userPatrons){

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildPatronsInfo(player, patronsInfo, dataBuilder, userPatrons);
            buildPatronsHalo(player, patronsInfo, dataBuilder, userPatrons);
            dataBuilder.build(EventDataConstants.Patrons.GUEST_LEVEL,  userPatrons.getLevel());
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Patrons.GET_GUEST, dataBuilder.getDataMap());

            DataBuilder userAttrBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            //门客列表
            List<Integer> patronsList = getPatronsList(player);
            userAttrBuilder.build(eUserAttr.CURRENT_GUEST_LIST.getAttrId(), patronsList.size());
            provider.user_set(userAttrBuilder.getAccountId(), userAttrBuilder.getDistinctId(), userAttrBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackAddPatrons error ", e);
        }

    }

    public static void buildPatronsInfo(GamePlayer player, PatronsInfo patronsInfo, DataBuilder dataBuilder, UserPatrons userPatrons) {
        dataBuilder.build(EventDataConstants.Patrons.GUEST_ID, patronsInfo.getId());

//        buildPatronsHalo(player, patronsInfo, dataBuilder, userPatrons);

        //缘分
        List<Map<String, Object>> fateList = new ArrayList<>();

        CalcPatronsAbilityParam calcPatronsAbilityParam = player.getModule(PatronsModule.class).buildCalcPatronsAbilityParam();
        List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_PATRONS_SKILL, "\\|");
        long addOne = PatronsMgr.getBeautyAddRegular(userPatrons, calcPatronsAbilityParam.getBeautyMap());
        Map<String, Object> addOneMap = new HashMap<>();
        addOneMap.put(EventDataConstants.Patrons.YF_TYPE, 1);
        addOneMap.put(EventDataConstants.Patrons.YF_ID, skillList.get(0));
        addOneMap.put(EventDataConstants.Patrons.YF_NUM, addOne);
        fateList.add(addOneMap);
        long addTow = PatronsMgr.getBeautyAddPercentage(userPatrons, calcPatronsAbilityParam.getBeautyMap());
        Map<String, Object> addTwoMap = new HashMap<>();
        addOneMap.put(EventDataConstants.Patrons.YF_TYPE, 1);
        addOneMap.put(EventDataConstants.Patrons.YF_ID, skillList.get(1));
        addOneMap.put(EventDataConstants.Patrons.YF_NUM, addTow);
        fateList.add(addTwoMap);

        //庄园
        long addThree = ManorMgr.getManorAddValue(userPatrons.getPatronsId(), calcPatronsAbilityParam.getManorTechnologyDataMap(), eSkillType.ManorPatronsAbilityAddValue.getValue());
        Map<String, Object> map = new HashMap<>();
        if(addThree > 0) {
            map.put(EventDataConstants.Patrons.YF_TYPE, 0);
            map.put(EventDataConstants.Patrons.YF_ID, eSkillType.ManorPatronsAbilityAddValue.getValue());
            map.put(EventDataConstants.Patrons.YF_NUM, addThree);
            fateList.add(map);
        }


        long addFour = ManorMgr.getManorAddValue(userPatrons.getPatronsId(), calcPatronsAbilityParam.getManorTechnologyDataMap(), eSkillType.ManorPatronsQualificationAddValue.getValue());
        if(addFour > 0) {
            map = new HashMap<>();
            map.put(EventDataConstants.Patrons.YF_TYPE, 0);
            map.put(EventDataConstants.Patrons.YF_ID, eSkillType.ManorPatronsQualificationAddValue.getValue());
            map.put(EventDataConstants.Patrons.YF_NUM, addFour);
            fateList.add(map);
        }
        dataBuilder.build(EventDataConstants.Patrons.GUEST_FATE, fateList);
        dataBuilder.build(EventDataConstants.Patrons.GUEST_VOCATION, patronsInfo.getOccupation());
        dataBuilder.build(EventDataConstants.Patrons.GUEST_INTELLIGENCE, userPatrons.getTotalQualification());
        dataBuilder.build(EventDataConstants.Patrons.GUEST_FIRSTQUELITY, patronsInfo.getQuality());
        if(userPatrons.getShowPromotionId() > 0){
            PromotionInfo promotionInfo = PromotionMgr.getPromotionInfoById(userPatrons.getShowPromotionId());
            if(promotionInfo != null){
                dataBuilder.build(EventDataConstants.Patrons.GUEST_QUELITY, promotionInfo.getQuality());
            }
        }else {
            dataBuilder.build(EventDataConstants.Patrons.GUEST_QUELITY, patronsInfo.getQuality());
        }
        buildPublicEventData(player, dataBuilder);
    }

    private static void buildPatronsHalo(GamePlayer player, PatronsInfo patronsInfo, DataBuilder dataBuilder, UserPatrons userPatrons) {

        //光环
        for (UserPatronsSkill skill : userPatrons.getSkillList()) {

        }
        //dataBuilder.build(EventDataConstants.Patrons.GUEST_HALO, StringUtils.listToString(patronsInfo.getTalentList(), ";"));

    }

    /**
     * 门客升级
     */
    public static void trackPatronsUpgrade(GamePlayer player, PatronsInfo patronsInfo, UserPatrons userPatrons, int add){

        try{
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildPatronsInfo(player, patronsInfo, dataBuilder, userPatrons);
            dataBuilder.build(EventDataConstants.Patrons.GUEST_LEVEL, userPatrons.getLevel() - add);
            dataBuilder.build(EventDataConstants.Patrons.GUEST_AFTER_LEVEL, userPatrons.getLevel());
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Patrons.GUEST_LEVEL_UP, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackPatronsUpgrade error ", e);
        }

    }

    /**
     * 门客升星
     */
    public static void trackPatronsStage(GamePlayer player, PatronsInfo patronsInfo, UserPatrons userPatrons, int add) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildPatronsInfo(player, patronsInfo, dataBuilder, userPatrons);
            buildPatronsHalo(player, patronsInfo, dataBuilder, userPatrons);
            dataBuilder.build(EventDataConstants.Patrons.GUEST_LEVEL, userPatrons.getLevel());
            dataBuilder.build(EventDataConstants.Patrons.GUEST_AFTER_STAR, userPatrons.getStageLv());
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Patrons.GUEST_STAR_UP, dataBuilder.getDataMap());
        } catch (Exception e) {
            logger.error("analytics trackPatronsStage error ", e);
        }
    }

    /**
     * 门客技能升级
     */
    public static void trackSkillUpgrade(GamePlayer player, PatronsInfo patronsInfo, UserPatrons userPatrons, UserPatronsSkill userPatronsSkill, int oldLv) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildPatronsInfo(player, patronsInfo, dataBuilder, userPatrons);
            dataBuilder.build(EventDataConstants.Patrons.GUEST_LEVEL, userPatrons.getLevel());
            dataBuilder.build(EventDataConstants.Patrons.GUEST_SKILL_NAME, userPatronsSkill.getSkillId());
            dataBuilder.build(EventDataConstants.Patrons.GUEST_AFTER_LEVEL, userPatronsSkill.getSkillLv());
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Patrons.GUEST_SKILL_UP, dataBuilder.getDataMap());

        }catch (Exception e){
            logger.error("analytics trackSkillUpgrade error ", e);
        }
    }

    /**
     * 夺宝
     */
    public static void trackTurntableLottery(GamePlayer player, int type, List<Property> rewardList, Property consume) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Recruit.RECRUIT_TYPE, type);
            JSONArray array = new JSONArray();
            for (Property property : rewardList) {
                for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
                    JSONObject object = new JSONObject();
                    object.put("item_id", entry.getKey());
                    object.put("item_num", entry.getValue().longValue());
                    array.add(object);
                }
            }
            dataBuilder.build(EventDataConstants.Recruit.ITEM_INFO, array);
            dataBuilder.build(EventDataConstants.Recruit.RECRUIT_COST_NUM, consume.getCountByGoodsId(GameConfig.GAME_ITEM_TURNTABLE_LOTTERY).intValue());
            dataBuilder.build(EventDataConstants.Recruit.RECRUIT_CART_ID, GameConfig.GAME_ITEM_TURNTABLE_LOTTERY);
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Recruit.RECRUIT, dataBuilder.getDataMap());

        }catch (Exception e){
            logger.error("analytics trackTurntableLottery error ", e);
        }
    }

    /**
     * 商铺建造
     */
    public static void trackBuildingCreate(GamePlayer player, int buildingId, BigInteger earnSpeed, BigInteger oldEarnSpeed) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.ShopBuilding.SHOP_NAME, buildingId);
            dataBuilder.build(EventDataConstants.ShopBuilding.SPEED, earnSpeed.longValue());
            dataBuilder.build(EventDataConstants.ShopBuilding.SPEED_ADD, earnSpeed.subtract(oldEarnSpeed).longValue());
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.ShopBuilding.SHOP_CREATE, dataBuilder.getDataMap());

            DataBuilder userAttrBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            //当前商铺个数
            userAttrBuilder.build(eUserAttr.CURRENT_STORE_NUMBER.getAttrId(), player.getModule(BuildingModule.class).getBuildingMap().size());
            provider.user_set(userAttrBuilder.getAccountId(), userAttrBuilder.getDistinctId(), userAttrBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBuildingCreate error ", e);
        }

    }

    /**
     * 商铺升级
     */
    public static void trackBuildingLevelUp(GamePlayer player, int buildingId, UserBuilding userBuilding, BigInteger earnSpeed, BigInteger oldEarnSpeed) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.ShopBuilding.SHOP_NAME, buildingId);
            dataBuilder.build(EventDataConstants.ShopBuilding.SHOP_AFTER_LEVEL, userBuilding.getLevel());
            dataBuilder.build(EventDataConstants.ShopBuilding.SPEED_ADD, earnSpeed.subtract(oldEarnSpeed).longValue());
            dataBuilder.build(EventDataConstants.ShopBuilding.SPEED, earnSpeed.longValue());
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.ShopBuilding.SHOP_LEVELUP, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBuildingLevelUp error ", e);
        }
    }

    /**
     * 商铺招募
     */
    public static void trackBuildingRecruit(GamePlayer player, int buildingId, UserBuilding userBuilding, int count, int type, BigInteger earnSpeed) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.ShopBuilding.SHOP_NAME, buildingId);
            dataBuilder.build(EventDataConstants.ShopBuilding.RECRUIT_TYPE, type);
            dataBuilder.build(EventDataConstants.ShopBuilding.GUEST_NUM, userBuilding.getStaffCount());
            dataBuilder.build(EventDataConstants.ShopBuilding.SPEED, earnSpeed.toString());
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.ShopBuilding.SHOP_RECRUIT, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBuildingRecruit error ", e);
        }
    }

    /**
     * 乔迁
     */
    public static void trackEstateWarBuyRoom(GamePlayer player, UserEstateWarData userEstateWarData, long enemyUserId, int type, int pos, boolean isWin, BigInteger totalAbility, BigInteger enemyAbility){

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.EstateWar.CURRENT_MANSION, userEstateWarData.getType() + "-" + userEstateWarData.getPos());
            dataBuilder.build(EventDataConstants.EstateWar.OUR_SPEED, totalAbility.longValue());
            dataBuilder.build(EventDataConstants.EstateWar.OTHER_MANSION, type + "-" + pos);
            dataBuilder.build(EventDataConstants.EstateWar.OTHER_SPEED, enemyAbility.longValue());
            dataBuilder.build(EventDataConstants.EstateWar.OTHER_TYPE, enemyUserId);
            dataBuilder.build(EventDataConstants.EstateWar.BUY_RESULT, isWin);
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.EstateWar.BUY_ROOM, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackEstateWarBuyRoom error ", e);
        }
    }

    /**
     * 结识美女
     */
    public static void trackBeautyGet(GamePlayer player, BeautyInfo beautyInfo, UserBeauty userBeauty){
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, beautyInfo.getBeautyId());

            //初始品质
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_FIRSTQUELITY, beautyInfo.getQuality());
            //美名等级
            dataBuilder.build(EventDataConstants.Beauty.BEAUTY_NAME, userBeauty.getIdentityLv());
            dataBuilder.build(EventDataConstants.Beauty.VOCATION, beautyInfo.getOccupation());
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.GET_INTIMATE, dataBuilder.getDataMap());

            //美女列表
            DataBuilder userAttrBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            buildBeautyList(player, userAttrBuilder, eUserAttr.CURRENT_INTIMATE_LIST.getAttrId());
            provider.user_set(userAttrBuilder.getAccountId(), userAttrBuilder.getDistinctId(), userAttrBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackEstateWarBuyRoom error ", e);
        }
    }

    /**
     * 美女技能升级
     * @param type 0：赚钱；1、2：缘分技能；3、4：才艺技能；5、6：皮肤技能
     */
    public static void trackBeautySkillUp(GamePlayer player, UserBeauty userBeauty, int skillId, int type, int nowLv) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, userBeauty.getBeautyId());

            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_SKILLNAME, skillId);
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_SKILLTYPE, type);
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_AFTERLEVEL, nowLv);
            //add v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.INTIMATE_SKILL_UP, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBeautySkillUp error ", e);
        }
    }

    /**
     * 赠送美女礼物
     */
    public static void trackSendBeautyGift(GamePlayer player, UserBeauty userBeauty, int giftId, int addValue, int type) {

        try {
            if (!openDataAnalytics()) return;
            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, userBeauty.getBeautyId());

            dataBuilder.build(EventDataConstants.Beauty.GIT_NAME, giftId);
            //亲密度
            if(type == 1){
                dataBuilder.build(EventDataConstants.Beauty.INTIMATE_ADD_LOVE, addValue);
                dataBuilder.build(EventDataConstants.Beauty.INTIMATE_LOVE, userBeauty.getTotalIntimacy());
            }else if(type == 2){
                dataBuilder.build(EventDataConstants.Beauty.INTIMATE_ADD_FLOWER, addValue);
                dataBuilder.build(EventDataConstants.Beauty.INTIMATE_FLOWER, userBeauty.getTotalGlamour());
            }
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.SEND_INTIMATE_GIFT, dataBuilder.getDataMap());
        } catch (Exception e) {
            logger.error("analytics trackSendBeautyGift error ", e);
        }
    }

    /**
     * 美名晋升
     */
    public static void trackBeautyPromotion(GamePlayer player, UserBeauty userBeauty) {

        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, userBeauty.getBeautyId());

            dataBuilder.build(EventDataConstants.Beauty.AFTER_BEAUTY_NAME, userBeauty.getIdentityLv());
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.PROMOTION_BEAUTY, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBeautyPromotion error ", e);
        }
    }

    /**
     * 美女游玩
     */
    public static void trackBeautyTrip(GamePlayer player, UserBeauty userBeauty, int type) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, userBeauty.getBeautyId());

            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_TRIPTYPE, type);
            //v4.1
            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.INTIMATE_TRIP, dataBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics trackBeautyPromotion error ", e);
        }

    }

    /**
     * 美女服装
     */
    public static void trackBeautySkin(GamePlayer player, UserBeauty userBeauty, UserSkin userSkin, int piecesGetWay, int size) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.Beauty.INTIMATE_NAME, userBeauty.getBeautyId());
            dataBuilder.build(EventDataConstants.Beauty.SUM_CLOTHING, size);
            dataBuilder.build(EventDataConstants.Beauty.CLOTHING_ID, userSkin.getSkinId());
            dataBuilder.build(EventDataConstants.Beauty.AFTER_LEVEL, userSkin.getLevel());
            buildPublicEventData(player, dataBuilder);
            if(piecesGetWay == 1){
                //解锁
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.INTIMATE_UNLOCK_CLOTHING, dataBuilder.getDataMap());
            }else {
                //升级
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Beauty.INTIMATE_CLOTHING_UP, dataBuilder.getDataMap());
            }
        }catch (Exception e){
            logger.error("analytics trackBeautySkin error ", e);
        }

    }

    /**
     * 关卡
     */
    public static void trackPassRoadBattle(GamePlayer player, boolean isWin, Property reward, UserPassRoad userPassRoad, int maxSilverBuffTimes, int maxItemBuffTimes, boolean isBoss){

        try {
            if (!openDataAnalytics()) return;

            //v4.1  只记录Boss 节点
            if(!isBoss){
                return;
            }

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));

            dataBuilder.build(EventDataConstants.Dungeon.DUNGEON_ID, userPassRoad.getPassId() + "-" + userPassRoad.getPassProgress());
            dataBuilder.build(EventDataConstants.Dungeon.DUNGEON_NAME, userPassRoad.getPassId());
            dataBuilder.build(EventDataConstants.Dungeon.DUNGEON_TYPE, isBoss ? "boss" : "normal");
            dataBuilder.build(EventDataConstants.Dungeon.CAR, userPassRoad.getTransportId());

            //v4.1补充公共事件
            buildPublicEventData(player, dataBuilder);
            //v4.1补充关卡失败的鼓舞道具记录
            List<String> useItemList = new ArrayList<>();
            useItemList.add(maxSilverBuffTimes + "");
            useItemList.add(maxItemBuffTimes + "");
            dataBuilder.build(EventDataConstants.Dungeon.USE_ITEM, useItemList);

            if(isWin){
                List<String> resourceList = new ArrayList<>();
                List<String> resourceNum = new ArrayList<>();
                for (Map.Entry<Integer, BigInteger> entry : reward.getGoods().entrySet()) {
                    resourceList.add("" + entry.getKey());
                    resourceNum.add("" + entry.getValue().toString());
                }
                dataBuilder.build(EventDataConstants.Dungeon.RESOURCE_GET, resourceList);
                dataBuilder.build(EventDataConstants.Dungeon.RESOURCE_NUM, resourceNum);
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Dungeon.DUNGEON_COMPLETED, dataBuilder.getDataMap());
            }else {
                provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Dungeon.DUNGEON_FAIL, dataBuilder.getDataMap());
            }
        }catch (Exception e){
            logger.error("analytics trackPassRoadBattle error ", e);
        }
    }

    /**
     * 钱庄升级
     */
    public static void trackHouseUpgrade(GamePlayer player, int houseLv) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder dataBuilder = DataBuilder.newBuilder(player.getUserId() + "", getDistinctId(player.getUserInfo()));
            dataBuilder.build(EventDataConstants.MoneyHouse.BEFORE_LEVEL, houseLv - 1);
            dataBuilder.build(EventDataConstants.MoneyHouse.AFTER_LEVEL, houseLv);

            buildPublicEventData(player, dataBuilder);
            provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.MoneyHouse.HOUSE_EXTEND, dataBuilder.getDataMap());

        }catch (Exception e){
            logger.error(e);
        }

    }

    public static void cacheUserCommonEvent(GamePlayer player){
        //公共事件属性
        DataBuilder common = DataBuilder.newBuilder(player.getUserInfo().getUserId(), DataAnalyticsMgr.getDistinctId(player.getUserInfo()));
        DataAnalyticsMgr.buildPublicEventData(player, common);
        commonUserEventDataMap.put(player.getUserId(), common);
    }

    public static DataBuilder getUserDataBuilder(long userId){
        return commonUserEventDataMap.get(userId);
    }

    public static void attactUserCommonEventData(DataBuilder dataBuilder, long userId){
        DataBuilder common = getUserDataBuilder(userId);
        if(common != null){
            dataBuilder.getDataMap().putAll(common.getDataMap());
        }
    }

    /**
     * 区服排行榜快照（个人）
     */
    public static void trackUserRankEvent(){
        if (!openDataAnalytics()) return;

        List<Integer> bigTypeList = new ArrayList<>();
        bigTypeList.add(eBigRankType.Normal.getValue());
        bigTypeList.add(eBigRankType.Skin.getValue());
        bigTypeList.add(eBigRankType.Vehicle.getValue());
        bigTypeList.add(eBigRankType.Patrons.getValue());
        bigTypeList.add(eBigRankType.Beauty.getValue());
        long serverId = ConfigHelper.getLong("serverId");
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);

        //先刷下上报
        DataAnalyticsMgr.flush();

        for (int bigType : bigTypeList) {
            Map<Integer, RankListModel> modelMap = RankMgr.getRankListModelMap(bigType);
            if(modelMap == null){
                continue;
            }
            for (Map.Entry<Integer, RankListModel> modelEntry : modelMap.entrySet()) {
                int rankType = modelEntry.getKey();
                if(bigType == eBigRankType.Normal.getValue()){
                    //如果是跨服的不上传
                    if(ActivityHelper.isCrossRankConditionType(rankType)){
                        continue;
                    }
                }
                RankListModel rankListModel = modelEntry.getValue();
                try{
                    DataBuilder dataBuilder = DataBuilder.newBuilder(EventDataConstants.Rank.RANK_ACCOUNT_ID, "");
                    dataBuilder.build(EventDataConstants.Rank.SERVER_ID, serverId);
                    if(serverInfo != null){
                        //dataBuilder.build(EventDataConstants.Rank.SERVER_NAME, serverInfo.getServerName());
                    }
                    dataBuilder.build(EventDataConstants.Rank.RANK_TYPE_ONE, bigType);
                    dataBuilder.build(EventDataConstants.Rank.RANK_TYPE_TWO, rankType);
                    List<RankProto.RankTempMsg> list = rankListModel.getRankListMsg().getRankListList();

                    JSONArray array = new JSONArray();
                    int size = list.size();
                    for (int i = 0; i < size && i < EventDataConstants.ARRAY_OBJECT_MAX_SIZE; i++) {
                        RankProto.RankTempMsg rank = list.get(i);
                        JSONObject object = new JSONObject();
                        object.put(EventDataConstants.Rank.RANKING, i + 1);
                        object.put(EventDataConstants.Rank.USERID, rank.getUserId());
                        object.put(EventDataConstants.Rank.LIST_VALUE, rank.getValue());
                        array.add(object);
                        if(i < 10){
                            dataBuilder.build("rank" + (i + 1), Arrays.asList(String.valueOf(rank.getUserId()), rank.getValue()));
                        }
                    }
                    dataBuilder.build(EventDataConstants.Rank.RANK, array);
                    provider.track(dataBuilder.getAccountId(), dataBuilder.getDistinctId(), EventDataConstants.Rank.RANK_EVENT, dataBuilder.getDataMap());
                }catch (Exception e){
                    logger.error("analytics trackUserRankEvent error {},{} ", bigType, rankType, e);
                }
            }
        }
        logger.debug("trackUserRankEvent finish");
    }

    public static Set<UserInfo> getActiveUser(int days){
        int zeroTime = DateHelper.getTodayZeroTime();
        List<UserInfo> list = UserMgr.getUserInfoList();
        //活动开始3天内有登录过的
        list.removeIf(userInfo -> userInfo.getLastLoginTime() < zeroTime - days * DateHelper.DAY_SECONDS);
        Set<UserInfo> set = new HashSet<>();
        set.addAll(list);
        for (GamePlayer player : GamePlayerMgr.getCopyPlayerList()) {
            set.add(player.getUserInfo());
        }
        return set;
    }


    /**
     * 账号注册埋点
     */
    public static void createCount(UserInfo userInfo) {
        try {
            if (!openDataAnalytics()) return;

            DataBuilder builder = DataBuilder.newBuilder(userInfo.getUserId() + "", getDistinctId(userInfo));
            long serverId = ConfigHelper.getInt("serverId");
            ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
            //openId
            builder.build(eUserAttr.OPEN_ID.getAttrId(), userInfo.getOpenId());
            //区服id
            builder.build(eUserAttr.SERVER_ID.getAttrId(), serverId);
            if(serverInfo != null){
                builder.build(eUserAttr.SERVER_NAME.getAttrId(), serverInfo.getServerName());
                builder.build(eUserAttr.CHANNEL_ID.getAttrId(), serverInfo.getChannelId());
                builder.build(eUserAttr.SERVER_TIME.getAttrId(), DateHelper.getCurrentDateTimeString(serverInfo.getOpenTime() * 1000));

                eChannelType channelType = eChannelType.forValue(serverInfo.getChannelId());
                if(channelType != null){
                    builder.build(eUserAttr.CHANNEL.getAttrId(), channelType.getName());
                }
            }
            if(!StringUtils.isNullOrEmpty(userInfo.getPlatformUserId())){
                builder.build(eUserAttr.PLATFORM_ID.getAttrId(), userInfo.getPlatformUserId());
            }
            if(userInfo.getUserId() > 0){
                builder.build(eUserAttr.USERID_ID.getAttrId(), userInfo.getUserId());
            }
            builder.build(eUserAttr.USERALIAS_ID.getAttrId(), userInfo.getUserAliasId());

            builder.build(eUserAttr.CREATE_ACCOUNT_TIME.getAttrId(), DateHelper.getCurrentDateTimeString());
            provider.user_setOnce(builder.getAccountId(), builder.getDistinctId(), builder.getDataMap());

            //注册事件
            DataBuilder registerBuilder = DataBuilder.newBuilder(userInfo.getUserId(), getDistinctId(userInfo));
            buildPublicEventData(userInfo, registerBuilder);
            provider.track(registerBuilder.getAccountId(), registerBuilder.getDistinctId(), EventDataConstants.Base.REGISTER, registerBuilder.getDataMap());
        }catch (Exception e){
            logger.error("analytics createCount error ", e);
        }
    }

    public static String getChannelPayType(long serverId){
        int channelId = 0;
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if (null != serverInfo) {
            channelId = serverInfo.getChannelId();
        } else {
            if (!StringUtils.isNullOrEmpty(ConfigHelper.getValue("channelId"))) {
                channelId = ConfigHelper.getInt("channelId");
            }
        }
        return getChannelPayType(channelId);
    }

    public static String getChannelPayType(int channelId){
        if(eChannelType.isMainLandChannel(channelId)){
            return "CNY";
        }
        if(eChannelType.isTwChannel(channelId) || eChannelType.InnerChannel.getValue() == channelId){
            return "TWD";
        }
        if(eChannelType.isJapanChannel(channelId)){
            return "JPY";
        }
        if(eChannelType.isKrChannel(channelId)){
            return "KRW";
        }
        if(eChannelType.isThinChannel(channelId) || eChannelType.isUkChannel(channelId) || eChannelType.isUsChannel(channelId)){
            return "USD";
        }
        if(eChannelType.isVnChannel(channelId)){
            return "VND";
        }
        return "";
    }

    public static ThreadTaskManger getThreadTaskManger() {
        return threadTaskManger;
    }

    public static void addTask(GeneralTask task){
        int id = DataAnalyticsMgr.taskId.getAndIncrement();
        if(id >= Integer.MAX_VALUE - 1000){
            DataAnalyticsMgr.taskId = new AtomicInteger(1);
        }
        threadTaskManger.addTask(id, task);
    }

    public static UserDayOnlineData getUserDayOnlineData(long userId){
        UserDayOnlineData data = userOnlineDataMap.get(userId);
        if(data == null){
            synchronized (userOnlineDataMap){
                data = userOnlineDataMap.get(userId);
                if(data == null){
                    data = new UserDayOnlineData();
                    data.setInsertOption();
                    data.setResetTime(DateHelper.getTodayZeroTime());
                    data.setUserId(userId);
                    userOnlineDataMap.put(userId, data);
                }
            }
        }
        return data;
    }

    public static void resetDayOnlineInfo(){

        if(userOnlineDataMap == null){
            return;
        }

        //今日0点
        long zeroTime = DateHelper.getTodayZeroTime();

        for (Map.Entry<Long, UserDayOnlineData> dataEntry : userOnlineDataMap.entrySet()) {
            UserDayOnlineData data = dataEntry.getValue();
            synchronized (lock){
                if(data.getResetTime() != zeroTime){

                    GamePlayer player = GamePlayerMgr.getOnlinePlayer(data.getUserId());
                    if(player != null){
                        //在线玩家，加上登录以来的时间
                        addDayOnlineTime(player, zeroTime - (Math.max(player.getUserInfo().getLastLoginTime(), zeroTime - DateHelper.DAY_SECONDS)));
                    }

                    if(data.getOnline() > 0 || data.getLoginTimes() > 0){
                        //上传昨日在线时长
                        if(player != null) {
                            OnLineLog.markOnlineTime(player, data.getLoginTimes(), data.getOnline(), data.getResetTime());
                        }else {
                            UserInfo userInfo = UserMgr.getUserInfo(data.getUserId());
                            if(userInfo != null){
                                OnLineLog.markOnlineTime(userInfo, data.getLoginTimes(), data.getOnline(), data.getResetTime());
                            }
                        }
                    }

                    //重置
                    data.setResetTime(zeroTime);
                    if(player == null){
                        data.setLoginTimes(0);
                    }else {
                        data.setLoginTimes(1);
                    }
                    data.setOnline(0);
                }
            }
        }
    }

    /**
     * 加登录次数
     */
    public static void addDayLoginTimes(GamePlayer player){
        long userId = player.getUserId();
        UserDayOnlineData data = getUserDayOnlineData(userId);
        long zeroTime = DateHelper.getTodayZeroTime();
        synchronized (lock){
            if(zeroTime == data.getResetTime()) {
                data.setLoginTimes(1 + data.getLoginTimes());
            }
        }
    }

    /**
     * 加在线时长(0点或者登出时记录)
     * @param times 秒
     */
    public static void addDayOnlineTime(GamePlayer player, long times){
        try{
            long userId = player.getUserId();
            UserDayOnlineData data = getUserDayOnlineData(userId);
            long zeroTime = DateHelper.getTodayZeroTime();
            synchronized (lock){
                if(zeroTime == data.getResetTime()) {
                    data.setOnline(times + data.getOnline());
                }
            }
        }catch (Exception e){
            getLogger().error("", e);
        }
    }

}
